package cResponse

import (
	"io"
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"

	"gitee.com/csingo/cCommon"
	"gitee.com/csingo/cError"
)

func Api(ctx *gin.Context, data interface{}, err error) (abort error) {
	var e cError.ErrorInterface
	var status = http.StatusOK

	switch ne := err.(type) {
	case validator.FieldError:
		e = cError.CError_Csingo_Param.Merge(ne)
	case validator.ValidationErrors:
		e = cError.CError_Csingo_Param.Merge(ne)
	case cError.ErrorInterface:
		e = err.(cError.ErrorInterface)
	case nil:
		e = cError.CError_Csingo_Nil
	default:
		e = cError.CError_Csingo_System.Merge(ne)
		status = http.StatusInternalServerError
	}

	if data == nil {
		data = struct{}{}
	}

	res := &ApiData{
		Code: e.Code(),
		Msg:  e.Error(),
		Data: data,
	}

	ctx.Set(cCommon.XIndex_ResponseCode, status)
	ctx.Set(cCommon.XIndex_ResponseData, res)

	ctx.JSON(status, res)

	return
}

func Json(ctx *gin.Context, data interface{}, err error) (abort error) {
	if err != nil {
		ctx.String(http.StatusInternalServerError, err.Error())
		return
	}

	ctx.Set(cCommon.XIndex_ResponseCode, http.StatusOK)
	ctx.Set(cCommon.XIndex_ResponseData, data)
	ctx.Header("Content-Type", "application/json;charset=UTF-8")
	ctx.JSON(http.StatusOK, data)

	return
}

func StringToHTML(ctx *gin.Context, data string, err error) (abort error) {
	if err != nil {
		ctx.String(http.StatusInternalServerError, err.Error())
		return
	}

	ctx.Set(cCommon.XIndex_ResponseCode, http.StatusOK)
	ctx.Set(cCommon.XIndex_ResponseData, data)
	ctx.Header("Content-Type", "text/html; charset=utf-8")
	ctx.String(http.StatusOK, data)

	return
}

func StringToJS(ctx *gin.Context, data string, err error) (abort error) {
	if err != nil {
		ctx.String(http.StatusInternalServerError, err.Error())
		return
	}

	ctx.Set(cCommon.XIndex_ResponseCode, http.StatusOK)
	ctx.Set(cCommon.XIndex_ResponseData, data)
	ctx.Header("Content-Type", "application/javascript; charset=utf-8")
	ctx.String(http.StatusOK, data)

	return
}

func StringToCSS(ctx *gin.Context, data string, err error) (abort error) {
	if err != nil {
		ctx.String(http.StatusInternalServerError, err.Error())
		return
	}

	ctx.Set(cCommon.XIndex_ResponseCode, http.StatusOK)
	ctx.Set(cCommon.XIndex_ResponseData, data)
	ctx.Header("Content-Type", "text/css; charset=utf-8")
	ctx.String(http.StatusOK, data)

	return
}

func Text(ctx *gin.Context, data string, err error) (abort error) {
	if err != nil {
		ctx.String(http.StatusInternalServerError, err.Error())
		return
	}

	ctx.Set(cCommon.XIndex_ResponseCode, http.StatusOK)
	ctx.Set(cCommon.XIndex_ResponseData, data)
	ctx.Header("Content-Type", "text/html; charset=utf-8")
	ctx.String(http.StatusOK, data)

	return
}

func Stream(ctx *gin.Context, messages chan string, err error) (abort error) {
	if err != nil {
		ctx.String(http.StatusInternalServerError, err.Error())
		return
	}

	ctx.Stream(func(w io.Writer) bool {
		msg := <-messages
		ctx.SSEvent("", " "+msg)

		return msg != cCommon.HTTPStreamEnd
	})
	ctx.Set(cCommon.XIndex_ResponseCode, http.StatusOK)
	return
}

func Redirect(ctx *gin.Context, url string, err error) (abort error) {
	if err != nil {
		ctx.String(http.StatusInternalServerError, err.Error())
		return
	}

	ctx.Redirect(http.StatusFound, url)
	return
}

func Empty(ctx *gin.Context, status ...int) (abort error) {
	result := http.StatusOK
	if len(status) > 0 {
		result = status[0]
	}
	ctx.Status(result)
	return
}

func File(ctx *gin.Context, fPath string, err error) (abort error) {
	if err != nil {
		ctx.String(http.StatusInternalServerError, err.Error())
		return
	}

	ctx.File(fPath)

	return
}
